/**
 * 
 */
package com.ap.core.bulkupload.service.impl;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import javax.xml.namespace.QName;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ap.core.bulkupload.listener.ParserListener;
import com.ap.core.bulkupload.listener.handler.ParseListenerHandler;
import com.ap.core.bulkupload.service.XmlParserService;
import com.ap.core.exception.APCoreException;
import com.ap.core.jaxb.ModelIterator;
import com.ap.core.jaxb.impl.JaxbStaxPullModelUnmarshaller;

// TODO: Auto-generated Javadoc
/**
 * The Class DefaultXmlParserService.
 * 
 * @author Siva.Pochana
 */
public class DefaultXmlParserService implements XmlParserService {

	/** The unmarshaller context map. */
	private Map<QName, String> unmarshallerContextMap;

	/** The type mapping. */
	private Map<QName, Class<?>> typeMapping;

	/** The parse listener handler. */
	private Map<String, ParseListenerHandler<Object>> parseListenerHandler;

	/** The log. */
	private static final Logger log = LoggerFactory
			.getLogger(DefaultXmlParserService.class);

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ap.core.bulkupload.service.XmlParserService#parse(java.io.InputStream
	 * , com.ap.core.bulkupload.listener.ParserListener)
	 */
	@Override
	public void parse(InputStream inputStream, ParserListener parserListner)
			throws APCoreException {
		try {
			JaxbStaxPullModelUnmarshaller unmarshaller = new JaxbStaxPullModelUnmarshaller();
			ModelIterator modelIterator = unmarshaller.unmarshall(inputStream,
					unmarshallerContextMap, typeMapping);
			while (modelIterator.hasNext()) {
				Object jaxbElement = modelIterator.next();
				parseListenerHandler
						.get(jaxbElement.getClass().getSimpleName())
						.handleParsing(jaxbElement, parserListner);
			}
		} catch (Exception e) {
			log.error("Exception occurred while processing parse() ["
					+ e.getMessage() + "]");
			throw new APCoreException(e);
		}
	}

	/**
	 * Sets the type mapping.
	 * 
	 * @param typeMappingStr
	 *            the type mapping str
	 * @throws APCoreException
	 *             the aP core exception
	 */
	@Override
	public void setTypeMapping(Map<String, String> typeMappingStr)
			throws APCoreException {

		this.typeMapping = new HashMap<>();
		try {
			for (Map.Entry entry : typeMappingStr.entrySet()) {
				this.typeMapping.put(QName.valueOf((String) entry.getKey()),
						Class.forName((String) entry.getValue()));
			}

		} catch (ClassNotFoundException e) {
			log.error("ClassNotFoundException error ocurred [" + e.getMessage()
					+ "]");
			throw new APCoreException(e);
		}
	}

	/**
	 * Sets the unmarshaller context map.
	 * 
	 * @param unmarshallerContextMap
	 *            the unmarshaller context map
	 */
	public void setUnmarshallerContextMap(
			Map<String, String> unmarshallerContextMap) {
		this.unmarshallerContextMap = new HashMap<>();
		for (Map.Entry entry : unmarshallerContextMap.entrySet()) {
			this.unmarshallerContextMap.put(QName.valueOf((String) entry.getKey()),
					(String)entry.getValue());
		}

	}

	/**
	 * Sets the parse listener handler.
	 * 
	 * @param parseListenerHandler
	 *            the parseListenerHandler to set
	 */
	public void setParseListenerHandler(
			Map<String, ParseListenerHandler<Object>> parseListenerHandler) {
		this.parseListenerHandler = parseListenerHandler;
	}
}
